package tools

import (
	"context"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
)

// FileTool provides file operation capabilities
type FileTool struct {
	workdir string
}

// NewFileTool creates a new file tool
func NewFileTool(workdir string) *FileTool {
	return &FileTool{
		workdir: workdir,
	}
}

// Name implements Tool
func (t *FileTool) Name() string {
	return "file"
}

// Description implements Tool
func (t *FileTool) Description() string {
	return "Performs file operations like read, write, and list"
}

// Parameters implements Tool
func (t *FileTool) Parameters() []Parameter {
	return []Parameter{
		{
			Name:        "operation",
			Type:        "string",
			Description: "Operation to perform (read, write, list, delete)",
			Required:    true,
		},
		{
			Name:        "path",
			Type:        "string",
			Description: "File or directory path",
			Required:    true,
		},
		{
			Name:        "content",
			Type:        "string",
			Description: "Content to write (for write operation)",
			Required:    false,
		},
	}
}

// Execute implements Tool
func (t *FileTool) Execute(ctx context.Context, params map[string]interface{}) (interface{}, error) {
	operation, ok := params["operation"].(string)
	if !ok {
		return nil, fmt.Errorf("operation parameter is required")
	}

	path, ok := params["path"].(string)
	if !ok {
		return nil, fmt.Errorf("path parameter is required")
	}

	// Ensure path is within workdir
	fullPath := filepath.Join(t.workdir, path)
	if !filepath.HasPrefix(fullPath, t.workdir) {
		return nil, fmt.Errorf("path must be within working directory")
	}

	switch operation {
	case "read":
		return t.readFile(fullPath)
	case "write":
		content, _ := params["content"].(string)
		return t.writeFile(fullPath, content)
	case "list":
		return t.listDir(fullPath)
	case "delete":
		return t.deleteFile(fullPath)
	default:
		return nil, fmt.Errorf("unknown operation: %s", operation)
	}
}

func (t *FileTool) readFile(path string) (string, error) {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return "", fmt.Errorf("failed to read file: %v", err)
	}
	return string(data), nil
}

func (t *FileTool) writeFile(path string, content string) (bool, error) {
	err := ioutil.WriteFile(path, []byte(content), 0644)
	if err != nil {
		return false, fmt.Errorf("failed to write file: %v", err)
	}
	return true, nil
}

func (t *FileTool) listDir(path string) ([]string, error) {
	files, err := ioutil.ReadDir(path)
	if err != nil {
		return nil, fmt.Errorf("failed to list directory: %v", err)
	}

	var names []string
	for _, file := range files {
		names = append(names, file.Name())
	}
	return names, nil
}

func (t *FileTool) deleteFile(path string) (bool, error) {
	err := os.Remove(path)
	if err != nil {
		return false, fmt.Errorf("failed to delete file: %v", err)
	}
	return true, nil
}
